
// <copyright file="HtmlDomHelper.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The html dom helper.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Windows.Forms
{
    using System;
    using System.Linq;
    using System.Windows.Forms;

    /// <summary>
    /// The html dom helper.
    /// </summary>
    public class HtmlDomHelper
    {
        // public string GetMessage(HtmlDocument document)
        // {
        // HtmlElement element = GetElementByTagNameAndText(document, "TD", "&nbsp;Messages", false);
        // if (element != null)
        // {
        // return element.Parent.Parent.Children[1].Children[0].InnerText;
        // }
        // return null;
        // }
        #region Public Methods and Operators

        /// <summary>
        /// The append option to drop down list.
        /// </summary>
        /// <param name="document">
        /// The document.
        /// </param>
        /// <param name="dropDownList">
        /// The drop down list.
        /// </param>
        /// <param name="option">
        /// The option.
        /// </param>
        public static void AppendOptionToDropDownList(HtmlDocument document, HtmlElement dropDownList, string option)
        {
            HtmlElement optionElement = document.CreateElement("option");
            optionElement.SetAttribute("text", option);
            optionElement.SetAttribute("value", option);
            optionElement.InnerText = option;
            optionElement.InnerHtml = option;
            dropDownList.AppendChild(optionElement);
        }

        /// <summary>
        /// The get drop down selection.
        /// </summary>
        /// <param name="ddl">
        /// The ddl.
        /// </param>
        /// <param name="isInnerText">
        /// The is inner text.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string GetDropDownSelection(HtmlElement ddl, bool isInnerText)
        {
            return (from HtmlElement element in ddl.Children where element.GetAttribute("selected").ToUpper() == "TRUE" select isInnerText ? element.InnerText : element.GetAttribute("value")).FirstOrDefault();
        }

        /// <summary>
        /// The get element by tag name and text.
        /// </summary>
        /// <param name="document">
        /// The document.
        /// </param>
        /// <param name="tagName">
        /// The tag name.
        /// </param>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <param name="isInnerText">
        /// The is inner text.
        /// </param>
        /// <returns>
        /// The <see cref="HtmlElement"/>.
        /// </returns>
        public static HtmlElement GetElementByTagNameAndText(HtmlDocument document, string tagName, string text, bool isInnerText)
        {
            HtmlElementCollection elementsByTagName = document.GetElementsByTagName(tagName);
            if (elementsByTagName != null)
            {
                foreach (HtmlElement element in elementsByTagName)
                {
                    if (string.Compare(tagName, "IMG", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        string src = element.GetAttribute("src");
                        if (src != null)
                        {
                            if (src.ToLower().EndsWith(text.ToLower()))
                            {
                                return element;
                            }
                        }
                    }

                    if (isInnerText)
                    {
                        if (element.InnerText == text)
                        {
                            return element;
                        }

                        if (element.InnerText != null && text != null)
                        {
                            if (element.InnerText.Trim() == text.Trim())
                            {
                                return element;
                            }
                        }
                    }
                    else
                    {
                        if (element.InnerHtml == text)
                        {
                            return element;
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// The set drop down selection.
        /// </summary>
        /// <param name="ddl">
        /// The ddl.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="isInnerText">
        /// The is inner text.
        /// </param>
        public static void SetDropDownSelection(HtmlElement ddl, string value, bool isInnerText)
        {
            foreach (HtmlElement element in ddl.Children)
            {
                if (isInnerText)
                {
                    if (element.InnerText == value)
                    {
                        element.SetAttribute("selected", "true");
                    }
                }
                else if (element.GetAttribute("value") == value)
                {
                    element.SetAttribute("selected", "true");
                }
            }
        }

        /// <summary>
        /// The set drop down selection.
        /// </summary>
        /// <param name="ddl">
        /// The ddl.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="setIfDisabled">
        /// The set if disabled.
        /// </param>
        /// <param name="shouldAddOptionIfDoesNotExist">
        /// The should add option if does not exist.
        /// </param>
        /// <param name="isIndex">
        /// The is index.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool SetDropDownSelection(HtmlElement ddl, string value, bool setIfDisabled, bool shouldAddOptionIfDoesNotExist, bool isIndex)
        {
            if (!setIfDisabled)
            {
                if (!ddl.Enabled)
                {
                    return false;
                }
            }

            int index = -1;
            if (isIndex)
            {
                index = int.Parse(value);
            }

            bool valueSet = false;
            string selectedValue = GetDropDownSelection(ddl, true);
            if (selectedValue != value)
            {
                valueSet = setDropDownValue(ddl, value, index);
                if (valueSet)
                {
                    fireDdlOnChangeEvent(ddl);
                }
                else
                {
                    if (shouldAddOptionIfDoesNotExist)
                    {
                        AppendOptionToDropDownList(ddl.Document, ddl, value);
                        valueSet = setDropDownValue(ddl, value, index);
                        if (valueSet)
                        {
                            fireDdlOnChangeEvent(ddl);
                        }
                    }
                }
            }

            return valueSet;
        }

        #endregion Public Methods and Operators

        #region Methods

        /// <summary>
        /// The fire ddl on change event.
        /// </summary>
        /// <param name="ddl">
        /// The ddl.
        /// </param>
        private static void fireDdlOnChangeEvent(HtmlElement ddl)
        {
            object o = ddl.GetAttribute("onchange");
            if (o != null)
            {
                ddl.RaiseEvent("onchange");
            }
        }

        /// <summary>
        /// The set drop down value.
        /// </summary>
        /// <param name="ddl">
        /// The ddl.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="index">
        /// The index.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private static bool setDropDownValue(HtmlElement ddl, string value, int index)
        {
            int currentIndex = -1;
            foreach (HtmlElement element in ddl.Children)
            {
                currentIndex++;
                if (element.InnerText == value || (index > -1 && currentIndex == index))
                {
                    element.SetAttribute("selected", "True");
                    return true;
                }
            }

            return false;
        }

        #endregion Methods
    }
}
